import { Injectable, Inject, forwardRef } from '@nestjs/common';
import { ResultData } from 'src/common/utils/result';
import { CreateMenuDto, UpdateMenuDto, ListDeptDto } from './dto/index';
import { ListToTree, Uniq } from 'src/common/utils/index';
import { UserService } from '../user/user.service';
import { buildMenus } from './utils';
import { PrismaService } from '@/module/common/prisma/prisma.service';
import { pickEquals, pickLike } from '@/common/utils/prisma';
@Injectable()
export class MenuService {
    constructor(
        @Inject(forwardRef(() => UserService))
        private readonly userService: UserService,
        private readonly prisma: PrismaService
    ) { }

    async create(createMenuDto: CreateMenuDto) {
        const res = await this.prisma.menu.create({ data: createMenuDto })
        return ResultData.ok(res);
    }

    async findAll(query: ListDeptDto) {
        let where: any = {
            delFlag: '0',
            ...pickLike(query, ['menuName']),
            ...pickEquals(query, ['status']),
        }
        const res = await this.prisma.menu.findMany({
            where,
            orderBy: { orderNum: 'asc' },
        });
        return ResultData.ok(res);
    }

    async treeSelect() {
        const res = await this.prisma.menu.findMany({
            where: {
                delFlag: '0',
            },
            orderBy: { orderNum: 'asc' },
        });
        const tree = ListToTree(
            res,
            (m) => m.menuId,
            (m) => m.menuName,
        );
        return ResultData.ok(tree);
    }

    async roleMenuTreeselect(roleId: number): Promise<any> {
        const res = await this.prisma.menu.findMany({
            where: {
                delFlag: '0',
            },
            orderBy: [
                { orderNum: 'asc' },
                { parentId: 'asc' },
            ],
        })
        const tree = ListToTree(
            res,
            (m) => m.menuId,
            (m) => m.menuName,
        );
        const menuIds = await this.prisma.roleMenu.findMany({
            where: { roleId },
            select: {
                menuId: true
            },
        });
        const checkedKeys = menuIds.map((item) => {
            return item.menuId;
        });
        return ResultData.ok({
            menus: tree,
            checkedKeys
        });
    }

    async findOne(menuId: number) {
        const res = await this.prisma.menu.findUnique({
            where: {
                menuId,
                delFlag: '0',
            },
        })
        return ResultData.ok(res);
    }

    async update(updateMenuDto: UpdateMenuDto) {
        const res = await this.prisma.menu.update({
            where: {
                menuId: updateMenuDto.menuId,
            },
            data: updateMenuDto,
        })
        return ResultData.ok(res);
    }

    async remove(menuId: number) {
        const data = await this.prisma.menu.update({
            where: {
                menuId,
            },
            data: {
                delFlag: '1',
            },
        })
        return ResultData.ok(data);
    }

    async findMany(where: any) {
        return await this.prisma.menu.findMany(where);
    }

    /**
     * 根据用户ID查询菜单
     *
     * @param userId 用户ID
     * @return 菜单列表
     */
    async getMenuListByUserId(userId: number) {
        let menuWidthRoleList = [];
        const roleIds = await this.userService.getRoleIds([userId]);
        if (roleIds.includes(1)) {
            // 超管roleId=1，所有菜单权限
            menuWidthRoleList = await this.prisma.menu.findMany({
                where: {
                    delFlag: '0',
                    status: '0',
                },
                select: {
                    menuId: true,
                }
            });
        } else {
            // 查询角色绑定的菜单
            menuWidthRoleList = await this.prisma.roleMenu.findMany({
                where: { roleId: { in: roleIds } },
                select: { menuId: true },
            });
        }
        // 菜单Id去重
        const menuIds = Uniq(menuWidthRoleList.map((item) => item.menuId));
        // 菜单列表
        const menuList = await this.prisma.menu.findMany({
            where: {
                delFlag: '0',
                status: '0',
                menuId: {
                    in: menuIds
                },
            },
            orderBy: {
                orderNum: 'asc',
            },
        });
        // 构建前端需要的菜单树
        const menuTree = buildMenus(menuList);
        return menuTree;
    }
}
